home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / EffectEdit / UIElements.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  12.9 KB  |  469 lines

  1. // UIElements.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "effectedit.h"
  6. #include "UIElements.h"
  7.  
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13.  
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CUIElements
  16.  
  17. CUIElements::CUIElements()
  18. {
  19.     m_pMeshArrow = NULL;
  20.     m_pEffect = NULL;
  21.     m_pd3dFont = NULL;
  22.     m_fObjectRadius = 1.0f;
  23. }
  24.  
  25. CUIElements::~CUIElements()
  26. {
  27.     DeleteAllElements();
  28. }
  29.  
  30. HRESULT CUIElements::OnCreateDevice( LPDIRECT3DDEVICE9 pd3dDevice )
  31. {
  32.     if( m_pd3dFont == NULL )
  33.         D3DXCreateFont( pd3dDevice, -12, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  34.                         OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  35.                         _T("Arial"), &m_pd3dFont );
  36.  
  37.     D3DXLoadMeshFromXResource( NULL, (LPCSTR)MAKEINTRESOURCE(IDR_ARROW_X), "X", D3DXMESH_MANAGED, 
  38.         pd3dDevice, NULL, NULL, NULL, NULL, &m_pMeshArrow );
  39.     D3DXCreateEffectFromResource( pd3dDevice, NULL, MAKEINTRESOURCE(IDR_UIELEMENT_FX),
  40.         NULL, NULL, 0, NULL, &m_pEffect, NULL );
  41.  
  42.     return S_OK;
  43. }
  44.  
  45. HRESULT CUIElements::OnResetDevice( LPDIRECT3DDEVICE9 pd3dDevice )
  46. {
  47.     if( m_pEffect != NULL )
  48.         m_pEffect->OnResetDevice();
  49.     m_pd3dFont->OnResetDevice();
  50.     return S_OK;
  51. }
  52.  
  53. void CUIElements::OnLostDevice()
  54. {
  55.     if( m_pEffect != NULL )
  56.         m_pEffect->OnLostDevice();
  57.     m_pd3dFont->OnLostDevice();
  58. }
  59.  
  60. void CUIElements::OnDestroyDevice()
  61. {
  62.     DeleteEffectObjects();
  63.     SAFE_RELEASE( m_pMeshArrow );
  64.     SAFE_RELEASE( m_pEffect );
  65.     SAFE_RELEASE( m_pd3dFont );
  66. }
  67.  
  68. void CUIElements::SetInfo( UINT bbWidth, UINT bbHeight, D3DXMATRIX* pMatProj )
  69. {
  70.     m_bbWidth = bbWidth;
  71.     m_bbHeight = bbHeight;
  72.     m_matProj = *pMatProj;
  73. }
  74.  
  75. void CUIElements::SetMatView( D3DXMATRIX* pMatView )
  76. {
  77.     m_matView = *pMatView;
  78. }
  79.  
  80. HRESULT CUIElements::RenderArrow( BOOL bSelected )
  81. {
  82.     UINT numPasses;
  83.     if( bSelected )
  84.         m_pEffect->SetTechnique( m_pEffect->GetTechniqueByName("Selected") );
  85.     else
  86.         m_pEffect->SetTechnique( m_pEffect->GetTechniqueByName("Unselected") );
  87.     m_pEffect->Begin( &numPasses, 0 );
  88.     for( UINT iPass = 0; iPass < numPasses; iPass++ )
  89.     {
  90.         m_pEffect->BeginPass( iPass );
  91.         m_pMeshArrow->DrawSubset( 0 );
  92.         m_pMeshArrow->DrawSubset( 1 );
  93.         m_pEffect->EndPass();
  94.     }
  95.     m_pEffect->End();
  96.  
  97.     return S_OK;
  98. }
  99.  
  100. HRESULT CUIElements::Render( IDirect3DDevice9 *pd3dDevice )
  101. {
  102.     CUIElement* pUIElement;
  103.  
  104.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  105.     {
  106.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  107.         pUIElement->Render( pd3dDevice );
  108.     }
  109.     return S_OK;
  110. }
  111.  
  112. // Go through pEffect and hook up existing UI objects to parameters,
  113. // and create new UI objects for other parameters
  114. void CUIElements::InitEffectObjects( LPD3DXEFFECT pEffect )
  115. {
  116.     D3DXEFFECT_DESC EffectDesc;
  117.     D3DXPARAMETER_DESC ParamDesc;
  118.     D3DXHANDLE hParam;
  119.     D3DXHANDLE hAnnot;
  120.     CUIElement* pElement;
  121.     LPCSTR pstrName;
  122.     CString strParamName;
  123.     CString strAnnotName;
  124.  
  125.     pEffect->GetDesc( &EffectDesc );
  126.     for( UINT iParam = 0; iParam < EffectDesc.Parameters; iParam++ )
  127.     {
  128.         hParam = pEffect->GetParameter ( NULL, iParam );
  129.  
  130.         // See if param has a UIDirectional annotation
  131.         hAnnot = pEffect->GetAnnotationByName( hParam, "UIDirectional" );
  132.         if( hAnnot != NULL )
  133.         {
  134.             pEffect->GetParameterDesc( hParam, &ParamDesc );
  135.             strParamName = ParamDesc.Name;
  136.  
  137.             // See if we already have a UIElement with with that name
  138.             pEffect->GetString( hAnnot, &pstrName);
  139.             strAnnotName = pstrName;
  140.             if( FindElement( strAnnotName, &pElement ) )
  141.             {
  142.                 // Element exists, so hook it up to this hParam
  143.                 pElement->SetParamName( strParamName );
  144.                 pElement->SetParam( pEffect, hParam, FALSE );
  145.             }
  146.             else
  147.             {
  148.                 // Element doesn't exist, so create one based on the type
  149.                 CDirLight* pDirLight;
  150.                 pDirLight = new CDirLight(this);
  151.                 if( pDirLight == NULL )
  152.                     return;
  153.                 pDirLight->SetAnnotName( strAnnotName );
  154.                 pDirLight->SetParamName( strParamName );
  155.                 pDirLight->SetParam( pEffect, hParam, TRUE );
  156.                 m_UIElementList.AddHead( pDirLight );
  157.             }
  158.         }
  159.     }
  160.  
  161.     // Destroy any UIElements that aren't attached to a handle by now
  162.     CUIElement* pUIElement;
  163.  
  164.     POSITION pos1, pos2;
  165.     for( pos1 = m_UIElementList.GetHeadPosition(); (pos2 = pos1) != NULL;  )
  166.     {
  167.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos1 );
  168.         if( pUIElement->GetParamHandle() == NULL )
  169.         {
  170.             pUIElement = (CUIElement*)m_UIElementList.GetAt(pos2);
  171.             m_UIElementList.RemoveAt(pos2);
  172.             delete pUIElement;
  173.         }
  174.     }
  175. }
  176.  
  177. // Drop all effect-specific objects (parameter handles)
  178. void CUIElements::DeleteEffectObjects()
  179. {
  180.     CUIElement* pUIElement;
  181.  
  182.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  183.     {
  184.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  185.         pUIElement->SetParam(NULL, NULL, FALSE);
  186.     }
  187. }
  188.  
  189. BOOL CUIElements::FindElement( CString& strAnnotName, CUIElement** ppElement )
  190. {
  191.     *ppElement = NULL;
  192.  
  193.     CUIElement* pUIElement;
  194.  
  195.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  196.     {
  197.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  198.         if( pUIElement->GetAnnotName() == strAnnotName )
  199.         {
  200.             *ppElement = pUIElement;
  201.             return TRUE;
  202.         }
  203.     }    
  204.     return FALSE;
  205. }
  206.  
  207.  
  208. void CUIElements::SetEffectParameters( LPD3DXEFFECT pEffect )
  209. {
  210.     CUIElement* pUIElement;
  211.  
  212.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  213.     {
  214.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  215.         pUIElement->SetEffectParameters( pEffect );
  216.     }
  217. }
  218.  
  219. void CUIElements::HandleMouseDown( INT x, INT y, BOOL* pbSetCapture )
  220. {
  221.     *pbSetCapture = FALSE;
  222.  
  223.     CUIElement* pUIElement;
  224.  
  225.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  226.     {
  227.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  228.         pUIElement->HandleMouseDown( x, y, pbSetCapture );
  229.         if( *pbSetCapture )
  230.             return;
  231.     }
  232. }
  233.  
  234. void CUIElements::HandleMouseMove( INT x, INT y )
  235. {
  236.     CUIElement* pUIElement;
  237.  
  238.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  239.     {
  240.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  241.         pUIElement->HandleMouseMove( x, y );
  242.     }
  243. }
  244.  
  245. void CUIElements::HandleMouseUp()
  246. {
  247.     CUIElement* pUIElement;
  248.  
  249.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  250.     {
  251.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  252.         pUIElement->HandleMouseUp();
  253.     }
  254. }
  255.  
  256.  
  257. BOOL CUIElements::IsDragging()
  258. {
  259.     CUIElement* pUIElement;
  260.  
  261.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  262.     {
  263.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  264.         if( pUIElement->IsDragging() )
  265.             return TRUE;
  266.     }
  267.     return FALSE;
  268. }
  269.  
  270. void CUIElements::DeleteAllElements()
  271. {
  272.     CUIElement* pUIElement;
  273.  
  274.     for( POSITION pos = m_UIElementList.GetHeadPosition(); pos != NULL;  )
  275.     {
  276.         pUIElement = (CUIElement*)m_UIElementList.GetNext( pos );
  277.         delete pUIElement;
  278.     }
  279.     m_UIElementList.RemoveAll();
  280. }
  281.  
  282.  
  283. /////////////////////////////////////////////////////////////////////////////
  284. // CDirLight
  285.  
  286. CDirLight::CDirLight(CUIElements* pUIElements)
  287. {
  288.     m_pUIElements = pUIElements;
  289.     m_fTheta = D3DX_PI / 2;
  290.     m_fRho = -D3DX_PI / 4;
  291.     m_bDragging = FALSE;
  292.     m_bSelected = FALSE;
  293.     m_vec.x = 0.0f;
  294.     m_vec.y = 0.0f;
  295.     m_vec.z = 1.0f;
  296. }
  297.  
  298. void CDirLight::Update()
  299. {
  300.     FLOAT fScaleFactor = m_pUIElements->m_fObjectRadius * 0.25f;
  301.     D3DXMATRIX matScale;
  302.     D3DXMATRIX matTrans;
  303.     D3DXMATRIX matRot;
  304.     D3DXMatrixScaling( &matScale, fScaleFactor, fScaleFactor, fScaleFactor );
  305.     D3DXMatrixTranslation( &matTrans, 0, 0, m_pUIElements->m_fObjectRadius * 0.75f );
  306.     D3DXMatrixRotationYawPitchRoll( &matRot, m_fTheta, m_fRho, 0 );
  307.     m_matWorld = matScale * matTrans * matRot;
  308.  
  309.     D3DXVECTOR3 vec(0, 0, 1);
  310.     D3DXVec3TransformCoord( &m_vec, &vec, &m_matWorld );
  311.     m_vec = -m_vec;
  312.     D3DXVec3Normalize(&m_vec, &m_vec);
  313. }
  314.  
  315. void CDirLight::SetEffectParameters( LPD3DXEFFECT pEffect )
  316. {
  317.     Update();
  318.     if( m_hParam != NULL )
  319.     {
  320.         D3DXVECTOR4 vec(m_vec.x, m_vec.y, m_vec.z, 1.0f);
  321.         pEffect->SetVector( m_hParam, &vec );
  322.     }
  323. }
  324.  
  325. void CDirLight::Render( IDirect3DDevice9* pd3dDevice )
  326. {
  327.     pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
  328.     m_pUIElements->RenderArrow(m_bSelected);
  329.     if( m_bSelected )
  330.     {
  331.         D3DXVECTOR3 vec;
  332.         D3DXMATRIX mat;
  333.         mat = m_matWorld * m_pUIElements->m_matView * m_pUIElements->m_matProj;
  334.         vec.x = 0; vec.y = 0; vec.z = 0;
  335.         D3DXVec3TransformCoord( &vec, &vec, &mat );
  336.         vec.x = vec.x * m_pUIElements->m_bbWidth / 2 + m_pUIElements->m_bbWidth / 2;
  337.         vec.y = -vec.y * m_pUIElements->m_bbHeight / 2 + m_pUIElements->m_bbHeight / 2;
  338.         CString str;
  339.         str.Format(TEXT("%s\n(%0.2f, %0.2f, %0.2f)"), m_strAnnotName, m_vec.x, m_vec.y, m_vec.z );
  340.         RECT rc = { (LONG)vec.x + 1, (LONG)vec.y + 1, (LONG)vec.x + 1, (LONG)vec.y + 1 };
  341.         m_pUIElements->m_pd3dFont->DrawText( NULL, str, -1, &rc, DT_LEFT|DT_NOCLIP, 0xff000000 );
  342.         OffsetRect( &rc, -1, -1 );
  343.         m_pUIElements->m_pd3dFont->DrawText( NULL, str, -1, &rc, DT_LEFT|DT_NOCLIP, 0xffffffff );
  344.     }
  345. }
  346.  
  347. void CDirLight::SetParam( LPD3DXEFFECT pEffect, D3DXHANDLE hParam, BOOL bPickUpDefault )
  348. {
  349.     HRESULT hr;
  350.     D3DXVECTOR4 vec;
  351.     m_hParam = hParam;
  352.  
  353.     if( pEffect == NULL )
  354.         return;
  355.  
  356.     if( bPickUpDefault )
  357.     {
  358.         hr = pEffect->GetVector( hParam, &vec );
  359.  
  360.         if( vec.x == 0 && vec.y == 0 && vec.z == 0 )
  361.         {
  362.             m_fTheta = D3DX_PI / 2;
  363.             m_fRho = -D3DX_PI / 4;
  364.         }
  365.         else
  366.         {
  367.             vec = -vec;
  368.             D3DXVec4Normalize( &vec, &vec );
  369.             m_fTheta = atan2f(vec.x, vec.z);
  370.             m_fRho = -vec.y * D3DX_PI / 2;
  371.         }
  372.         Update();
  373.     }
  374. }
  375.  
  376. void CDirLight::HandleMouseDown( INT x, INT y, BOOL* pbSetCapture )
  377. {
  378.     *pbSetCapture = FALSE;
  379.     if( MouseOverLight( x, y ) ) 
  380.     {
  381.         *pbSetCapture = TRUE;
  382.         m_hCur = SetCursor(NULL);
  383.         m_bDragging = TRUE;
  384.         m_xDown = x;
  385.         m_yDown = y;
  386.         m_fThetaDown = m_fTheta;
  387.         m_fRhoDown = m_fRho;
  388.     }
  389. }
  390.  
  391. void CDirLight::HandleMouseMove( INT x, INT y )
  392. {
  393.     if( m_bDragging )
  394.     {
  395.         INT dx = m_xDown - x;
  396.         INT dy = y - m_yDown;
  397.  
  398.         float fdx = dx / 100.0f;
  399.         float fdy = dy / 100.0f;
  400.  
  401.         m_fTheta = m_fThetaDown + fdx;
  402.         m_fRho = m_fRhoDown + fdy;
  403.  
  404.         if( m_fRho > D3DX_PI / 2 )
  405.             m_fRho = D3DX_PI / 2;
  406.         if( m_fRho < -D3DX_PI / 2 )
  407.             m_fRho = -D3DX_PI / 2;
  408.         Update();
  409.     }
  410.     else
  411.     {
  412.         if( MouseOverLight( x, y ) ) 
  413.         {
  414.             m_bSelected = TRUE;
  415.         }
  416.         else
  417.         {
  418.             m_bSelected = FALSE;
  419.         }
  420.     }
  421. }
  422.  
  423. void CDirLight::HandleMouseUp()
  424. {
  425.     if( m_bDragging )
  426.     {
  427.         m_bDragging = FALSE;
  428.         ReleaseCapture();
  429.         SetCursor(m_hCur);
  430.         m_hCur = NULL;
  431.     }
  432. }
  433.  
  434. BOOL CDirLight::MouseOverLight(INT x, INT y)
  435. {
  436.     D3DXVECTOR3 vecRayPos;
  437.     D3DXVECTOR3 vecRayDir;
  438.     BOOL bHit = FALSE;
  439.  
  440.     D3DXVECTOR3 vPickRayDir;
  441.     D3DXVECTOR3 vPickRayOrig;
  442.  
  443.     // Get the pick ray from the mouse position
  444.  
  445.     // Compute the vector of the pick ray in screen space
  446.     D3DXVECTOR3 v;
  447.     v.x =  ( ( ( 2.0f * x ) / m_pUIElements->m_bbWidth  ) - 1 ) / m_pUIElements->m_matProj._11;
  448.     v.y = -( ( ( 2.0f * y ) / m_pUIElements->m_bbHeight ) - 1 ) / m_pUIElements->m_matProj._22;
  449.     v.z =  1.0f;
  450.  
  451.     // Get the inverse worldview matrix
  452.     D3DXMATRIXA16 m1, m;
  453.     m1 = m_matWorld * m_pUIElements->m_matView;
  454.     D3DXMatrixInverse( &m, NULL, &m1 );
  455.  
  456.     // Transform the screen space pick ray into 3D space
  457.     vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
  458.     vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
  459.     vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
  460.     vPickRayOrig.x = m._41;
  461.     vPickRayOrig.y = m._42;
  462.     vPickRayOrig.z = m._43;
  463.     
  464.     D3DXIntersect( m_pUIElements->m_pMeshArrow, &vPickRayOrig, &vPickRayDir, &bHit, 
  465.         NULL, NULL, NULL, NULL, NULL, NULL );
  466.     return bHit;
  467. }
  468.  
  469.